<template>
  <div>
    <input
      ref="inputRef"
      type="file"
      v-show="false"
      accept=".xlsx, .xls"
      @change="handleInputClick"
    />
    <div @click="handleUpload">
      <slot></slot>
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent, ref, unref } from 'vue'
import XLSX from 'xlsx'
import { dateUtil } from '@admin/utils'

import type { ExcelData } from './typing'
export default defineComponent({
  name: 'ImportExcel',
  props: {
    // 日期时间格式。如果不提供或者提供空值，将返回原始Date对象
    dateFormat: {
      type: String,
    },
    // 时区调整。实验性功能，仅为了解决读取日期时间值有偏差的问题。目前仅提供了+08:00时区的偏差修正值
    // https://github.com/SheetJS/sheetjs/issues/1470#issuecomment-501108554
    timeZone: {
      type: Number,
      default: 8,
    },
  },
  emits: ['success', 'error'],
  setup(props, { emit }) {
    const inputRef = ref<HTMLInputElement | null>(null)
    const loadingRef = ref<Boolean>(false)

    /**
     * @description: 第一行作为头部
     */
    function getHeaderRow(sheet: XLSX.WorkSheet) {
      if (!sheet || !sheet['!ref']) return []
      const headers: string[] = []
      // A3:B7=>{s:{c:0, r:2}, e:{c:1, r:6}}
      const range = XLSX.utils.decode_range(sheet['!ref'])

      const R = range.s.r
      /* start in the first row */
      for (let C = range.s.c; C <= range.e.c; ++C) {
        /* walk every column in the range */
        const cell = sheet[XLSX.utils.encode_cell({ c: C, r: R })]
        /* find the cell in the first row */
        let hdr = 'UNKNOWN ' + C // <-- replace with your desired default
        if (cell && cell.t) hdr = XLSX.utils.format_cell(cell)
        headers.push(hdr)
      }
      return headers
    }

    /**
     * @description: 获得excel数据
     */
    function getExcelData(workbook: XLSX.WorkBook) {
      const excelData: ExcelData[] = []
      const { dateFormat, timeZone } = props
      for (const sheetName of workbook.SheetNames) {
        const worksheet = workbook.Sheets[sheetName]
        const header: string[] = getHeaderRow(worksheet)
        let results = XLSX.utils.sheet_to_json(worksheet, {
          raw: true,
          dateNF: dateFormat, //Not worked
        }) as object[]
        results = results.map((row: object) => {
          for (let field in row) {
            if (row[field] instanceof Date) {
              if (timeZone === 8) {
                row[field].setSeconds(row[field].getSeconds() + 43)
              }
              if (dateFormat) {
                row[field] = dateUtil(row[field]).format(dateFormat)
              }
            }
          }
          return row
        })

        excelData.push({
          header,
          results,
          meta: {
            sheetName,
          },
        })
      }
      return excelData
    }

    /**
     * @description: 读取excel数据
     */
    function readerData(rawFile: File) {
      loadingRef.value = true
      return new Promise((resolve, reject) => {
        const reader = new FileReader()
        reader.onload = async (e) => {
          try {
            const data = e.target && e.target.result
            const workbook = XLSX.read(data, {
              type: 'array',
              cellDates: true,
            })
            // console.log(workbook);
            /* DO SOMETHING WITH workbook HERE */
            const excelData = getExcelData(workbook)
            emit('success', excelData)
            resolve('')
          } catch (error) {
            reject(error)
            emit('error')
          } finally {
            loadingRef.value = false
          }
        }
        reader.readAsArrayBuffer(rawFile)
      })
    }

    async function upload(rawFile: File) {
      const inputRefDom = unref(inputRef)
      if (inputRefDom) {
        // fix can't select the same excel
        inputRefDom.value = ''
      }
      await readerData(rawFile)
    }

    /**
     * @description: 触发选择文件管理器
     */
    function handleInputClick(e: Event) {
      const files = e && (e.target as HTMLInputElement).files
      const rawFile = files && files[0] // only setting files[0]
      if (!rawFile) return
      upload(rawFile)
    }

    /**
     * @description: 点击上传按钮
     */
    function handleUpload() {
      const inputRefDom = unref(inputRef)
      inputRefDom && inputRefDom.click()
    }

    return { handleUpload, handleInputClick, inputRef }
  },
})
</script>
